package com.unmarshaller.propertiesunmarshaller;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Properties;

import javax.xml.bind.PropertyException;

import org.apache.log4j.Logger;

import com.unmarshaller.annotation.FilePath;
import com.unmarshaller.annotation.Property;

/**
 * properties配置数据解析
 * @author hongxiao.z
 * @date	2013-10-21
 */
public class PropertyUnmarshaller 
{
	private static Logger log = Logger.getLogger(PropertyUnmarshaller.class);
	
	/**
	 * 解组一个文件类
	 * @param clazz
	 * @return
	 * @throws Exception
	 * @date	2013-10-21
	 * @create	hongxiao.z
	 */
	public static void unmarshaller(Class<?> clazz) throws Exception
	{
		if(clazz == null)
		{
			return;
		}
		
		/*不存在路径注解*/
		if(!clazz.isAnnotationPresent(FilePath.class))
		{
			StringBuilder sb = new StringBuilder(clazz.getSimpleName()).append(" --- 查找不到对应的数据文件路径！");
			log.warn(sb.toString());
			return;
		}
		
		/*路径文件格式有错*/
		FilePath pathAnno = clazz.getAnnotation(FilePath.class);
		String path = pathAnno.value();
		/*获取文件后缀名*/
		String suffix = path.substring(path.lastIndexOf("."), path.length());
		
		if(!suffix.equals(".properties"))
		{
			StringBuilder sb = new StringBuilder(clazz.getSimpleName()).append(" --- 无法解析的文件类型！[").append(path).append("]");
			log.warn(sb.toString());
			return;
		}
		
		log.info(new StringBuilder(path).append(" >>> [").append(clazz.getSimpleName()).append("]").toString());
		
		unmarshaller(new File(path), clazz);
	}
	
	/**
	 * 配置文件对应key 赋值
	 * @param file
	 * @param clazz
	 * @return
	 * @throws PropertyException
	 * @date	2013-10-21
	 * @create	hongxiao.z
	 */
	private static void unmarshaller(File file, Class<?> clazz) throws Exception
	{
		Properties prop = PropertyUtil.load(file);
		
		for (Field field : clazz.getFields()) 
		{
			if(!Modifier.isStatic(field.getModifiers()))	//非静态
			{
				continue;
			}
			
			if(Modifier.isFinal(field.getModifiers()))		//final字段不能赋值
			{
				continue;
			}
			
			boolean old = field.isAccessible();
			field.setAccessible(true);
			
			setValue(prop, field);
			
			field.setAccessible(old);
		}
	}
	
	/**
	 * 设置赋值
	 * @param prop
	 * @param field
	 * @throws Exception
	 * @date	2013-10-21
	 * @create	hongxiao.z
	 */
	private static void setValue(Properties prop, Field field) throws Exception
	{
		/*没有注解*/
		if(!field.isAnnotationPresent(Property.class))
		{
			return;
		}
		
		Property pty = field.getAnnotation(Property.class);
		String value = prop.getProperty(pty.key());
		
		if(value == null)
		{
			value = pty.DEFAULTVALUE();
		}
		
		ITransformer itrans = null;

		try
		{
			itrans = PropertyTransformerFactory.getTransformer(field.getType());
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return;
		}

		itrans.transformer(field, value);
	}
}
